<!doctype html>
<html lang="zh-cn">
<head>

    <meta charset="utf-8">
    <meta name="generator" content="Hugo 0.57.2" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">

    <title>单例模式 | The Sky of OtsWang</title>
    <meta property="og:title" content="单例模式 - The Sky of OtsWang">
    <meta property="og:type" content="article">
        
    <meta property="article:published_time" content="2018-12-24T14:12:38&#43;08:00">
        
        
    <meta property="article:modified_time" content="2018-12-24T14:12:38&#43;08:00">
        
    <meta name="Keywords" content="golang,go语言,otswang,java,博客,python">
    <meta name="description" content="单例模式">
        
    <meta name="author" content="OtsWang">
    <meta property="og:url" content="https://otswang.gitee.io/hugo/post/design/single/">
    <link rel="shortcut icon" href="/favicon.ico" type="image/x-icon">

    <link rel="stylesheet" href="/hugo/css/normalize.css">
    
        <link rel="stylesheet" href="/hugo/css/prism.css">
    
    <link rel="stylesheet" href="/hugo/css/style.css">
    <script type="text/javascript" src="//cdn.bootcss.com/jquery/3.2.1/jquery.min.js"></script>

    


    
    
</head>

<body>
<header id="header" class="clearfix">
    <div class="container">
        <div class="col-group">
            <div class="site-name ">
                
                    <a id="logo" href="https://otswang.gitee.io/hugo/">
                        The Sky of OtsWang
                    </a>
                
                <p class="description">擅长写HelloWorld的小小码农</p>
            </div>
            <div>
                <nav id="nav-menu" class="clearfix">
                    
                    
                    <a  href="https://otswang.gitee.io/hugo/" title="Home">Home</a>
                    
                    <a  href="https://otswang.gitee.io/hugo/tags/" title="Tags">Tags</a>
                    
                    <a  href="https://otswang.gitee.io/hugo/categories/" title="Categories">Categories</a>
                    
                    <a  href="https://otswang.gitee.io/hugo/archives/" title="Archives">Archives</a>
                    
                    <a  href="https://otswang.gitee.io/hugo/about/" title="About">About</a>
                    
                </nav>
            </div>
        </div>
    </div>
</header>


<div id="body">
    <div class="container">
        <div class="col-group">

            <div class="col-8" id="main">
                <div class="res-cons">
                    <article class="post">
                        <header>
                            <h1 class="post-title">单例模式</h1>
                        </header>
                        <date class="post-meta meta-date">
                            2018年12月24日
                        </date>
                        
                        <div class="post-meta">
                            <span>|</span>
                            
                                <span class="meta-category"><a href="https://otswang.gitee.io/hugo/categories/design">Design</a></span>
                            
                        </div>
                        
                        
                        
                        <div class="post-content">
                            <p>单例模式，它的定义就是确保某一个类只有一个实例，并且提供一个全局访问点。共有五种形式：懒汉模式，懒汉双重校验锁模式，饿汉模式，内部类模式，枚举模式。现在最推荐的方式是枚举单例模式。</p>

<h2 id="懒汉模式">懒汉模式</h2>

<p>延时加载，线程不安全。</p>

<pre><code class="language-java">public class SluggardType {
    private static SluggardType instance = null;

    private SluggardType() {
        // init
    }

    public static SluggardType getInstance() {
        if (instance == null){
            instance = new SluggardType();
        }

        return instance;
    }

    public void say() {
        System.out.println(&quot;懒汉式模式单例&quot;);
    }

    public static void main(String[] args){
        SluggardType.getInstance().say();
    }
}
</code></pre>

<h2 id="懒汉模式-双重校验锁">懒汉模式-双重校验锁</h2>

<p>性能不好</p>

<pre><code class="language-java">public class SluggardType2 {

    private volatile static SluggardType2 instance = null;

    private SluggardType2() {
    }

    public static SluggardType2 getInstance(){
        if (instance == null){
            synchronized (SluggardType2.class){
                if (instance == null){
                    instance = new SluggardType2();// 使用volatile关键字使得此步不被优化
                }
            }
        }

        return instance;
    }

    public void say() {
        System.out.println(&quot;懒汉模式-双重校验锁-不推荐&quot;);
    }

    public static void main(String[] args){
        SluggardType2.getInstance().say();
    }
}
</code></pre>

<h2 id="恶汉模式">恶汉模式</h2>

<p>通过反射机制进行攻击，线程安全。</p>

<p>饿汉式单例在自己被加载时就将自己实例化，如果从资源利用效率角度来讲，比懒汉式单例类稍差些。但是从速度和反应时间角度来讲，则比懒汉式要稍好些。</p>

<pre><code class="language-java">public class HungryType {
    public static final HungryType instance = new HungryType();

    private HungryType() {
        // init
    }

    public void splitAlipay() {
        System.out.println(&quot;饿汉式单例模式&quot;);
    }

    public static void main(String[] args){
        HungryType ht = HungryType.instance;
        ht.splitAlipay();
    }

}
</code></pre>

<h2 id="内部类单例模式">内部类单例模式</h2>

<p>JVM提供线程安全保障</p>

<pre><code class="language-java">public class InnerClasssingleton {
    private static class SingletonHolder {
        private static InnerClasssingleton instance = new InnerClasssingleton();
    }
    /**
     * 类级的内部类，该内部类的实例与外部类的实例没有绑定关系，而且只有被调用到时才会装载（装载过程由JVM保证线程安全）
     * 从而实现了延迟加载
     */

    private InnerClasssingleton() {
        // 私有构造方法
    }

    public static InnerClasssingleton getInstance(){
        return SingletonHolder.instance;
    }

    public void say() {
        System.out.println(&quot;静态内部类实现单例模式-JVM保证线程安全&quot;);
    }

    public static void main(String[] args) {
        InnerClasssingleton.getInstance().say();
    }
}
</code></pre>

<h2 id="枚举单例模式">枚举单例模式</h2>

<p>推荐，线程安全</p>

<pre><code class="language-java">public class EnumSingleton {
    private EnumSingleton() {
        // 私有构造
    }

    public static EnumSingleton getInstance(){
        return Singleton.INSTANCE.getInstance();
    }

    public void say() {
        System.out.println(&quot;枚举实现单例模式-线程安全&quot;);
    }

    // default static
    private enum Singleton {
        INSTANCE;

        private EnumSingleton singleton;

        // default private
        Singleton() {
            // JVM保证此方法只被执行一次
            singleton = new EnumSingleton();
        }

        public EnumSingleton getInstance() {
            return singleton;
        }


    }

    public static void main(String[] args){
        EnumSingleton.getInstance().say();
    }
}
</code></pre>

<h2 id="spring中的单例模式">Spring中的单例模式</h2>

<p>Spring的依赖注入（包括lazy-init方式）都是发生在 AbstractBeanFactory 的 getBean 里。 getBean 的 doGetBean 方法调用 getSingleton 进行bean的创建。lazy-init方式(lazy-init=“true”)，在用户向容器第一次索要bean时进行调用；非lazy-init方式(lazy-init=“false”)，在容器初始化时候进行调用。</p>
                        </div>

                        


                        


                        <div class="post-meta meta-tags">
                            
                            <ul class="clearfix">
                                
                                <li><a href="https://otswang.gitee.io/hugo/tags/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F">设计模式</a></li>
                                
                            </ul>
                            
                        </div>
                    </article>
                    
    

    
    
                </div>
            </div>
            <div id="secondary">

    <section class="widget">
        <form id="search" action="//www.google.com/search" method="get" accept-charset="utf-8" target="_blank" _lpchecked="1">
      
      <input type="text" name="q" maxlength="20" placeholder="Search">
      <input type="hidden" name="sitesearch" value="https://otswang.gitee.io/hugo/">
      <button type="submit" class="submit icon-search"></button>
</form>
    </section>

    
    <div class="clear">
        <div class="toc-article">
            <div class="toc-title">文章目录</dixsv>
            <nav id="TableOfContents">
<ul>
<li>
<ul>
<li><a href="#懒汉模式">懒汉模式</a></li>
<li><a href="#懒汉模式-双重校验锁">懒汉模式-双重校验锁</a></li>
<li><a href="#恶汉模式">恶汉模式</a></li>
<li><a href="#内部类单例模式">内部类单例模式</a></li>
<li><a href="#枚举单例模式">枚举单例模式</a></li>
<li><a href="#spring中的单例模式">Spring中的单例模式</a></li>
</ul></li>
</ul>
</nav>
        </div>
    </div>
    

</div>
        </div>
    </div>
</div>
<footer id="footer">
    <div class="container">
        &copy; 2020 <a href="https://otswang.gitee.io/hugo/">The Sky of OtsWang By OtsWang</a>.
        Powered by <a rel="nofollow noreferer noopener" href="https://gohugo.io" target="_blank">Hugo</a>.
        <a href="https://www.flysnow.org/" target="_blank">Theme</a> based on <a href="https://github.com/Dudiao137/maupassant-hugo" target="_blank">maupassant-ots</a>.
        
    </div>
</footer>


    <script type="text/javascript">
    
    (function(){
        $("pre code").parent().addClass("line-numbers")
    }())

    window.MathJax = {
        tex2jax: {
            inlineMath: [ ['$','$'] ],
            processEscapes: true
        }
    };
    </script>
    <script type="text/javascript" src="/hugo/js/prism.js" async="true"></script>
    <script src='https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/MathJax.js?config=TeX-MML-AM_CHTML' async></script>

<a id="rocket" href="#top"></a>
<script type="text/javascript" src="/hugo/js/totop.js?v=0.0.0" async=""></script>







 
 <script src="https://mermaidjs.github.io/scripts/mermaid.min.js"></script>
 <script>
       mermaid.initialize({ startOnLoad: true });
 </script>
</body>
</html>
